home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
shadow-9.tar
/
shadow-9
/
shadow-960129
/
sulogin.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-17
|
8KB
|
305 lines
/*
* Copyright 1989 - 1994, John F. Haugh II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by John F. Haugh, II
* and other contributors.
* 4. Neither the name of John F. Haugh, II nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JOHN HAUGH AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL JOHN HAUGH OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef SVR4
#include <utmpx.h>
#else
#include <sys/types.h>
#include <utmp.h>
#endif
#include <signal.h>
#include <stdio.h>
#include "pwd.h"
#include <fcntl.h>
#include "config.h"
#include "prototypes.h"
#include "defines.h"
#include "pwauth.h"
#if defined(BSD) || defined(SUN)
#include <sgtty.h>
#define USE_SGTTY 1
#endif
#if defined(USG) || defined(SUN4)
#ifdef _POSIX_SOURCE
#include <termios.h>
#define USE_TERMIOS 1
#else
#include <termio.h>
#define USE_TERMIO 1
#endif
#endif
#ifdef USE_SYSLOG
#include <syslog.h>
#ifndef LOG_WARN
#define LOG_WARN LOG_WARNING
#endif
#endif
#ifndef lint
static char rcsid[] = "$Id: sulogin.c,v 1.2 1995/12/16 21:51:39 marekm Exp $";
#endif
char name[BUFSIZ];
char pass[BUFSIZ];
struct passwd pwent;
#ifdef SVR4
struct utmpx utent;
#else
struct utmp utent;
#endif
#ifdef USE_SGTTY
struct sgttyb termio;
#endif
#ifdef USE_TERMIO
struct termio termio;
#endif
#ifdef USE_TERMIOS
struct termios termio;
#endif
#ifndef MAXENV
#define MAXENV 64
#endif
char *newenvp[MAXENV];
int newenvc = 0;
int maxenv = MAXENV;
extern char **environ;
extern char *getpass();
extern char *getdef_str();
#ifndef ALARM
#define ALARM 60
#endif
#ifndef RETRIES
#define RETRIES 3
#endif
SIGTYPE
catch (sig)
int sig;
{
exit (1);
}
/*ARGSUSED*/
int
main (argc, argv, envp)
int argc;
char **argv;
char **envp;
{
char *getenv ();
char *ttyname ();
char *getpass ();
char *tz ();
char *cp;
#ifdef USE_SGTTY
ioctl (0, TIOCGETP, &termio);
termio.sg_flags |= (ECHO|CRMOD);
termio.sg_flags &= ~(RAW|CBREAK);
ioctl (0, TIOCSETN, &termio);
#endif
#ifdef USE_TERMIO
ioctl (0, TCGETA, &termio);
termio.c_iflag |= (ICRNL|IXON);
termio.c_oflag |= (OPOST|ONLCR);
termio.c_cflag |= (CREAD);
termio.c_lflag |= (ISIG|ICANON|ECHO|ECHOE|ECHOK);
ioctl (0, TCSETAF, &termio);
#endif
#ifdef USE_TERMIOS
tcgetattr (0, &termio);
termio.c_iflag |= (ICRNL|IXON);
termio.c_oflag |= (CREAD);
termio.c_lflag |= (ECHO|ECHOE|ECHOK|ICANON|ISIG);
tcsetattr (0, TCSANOW, &termio);
#endif
#ifdef USE_SYSLOG
openlog ("sulogin", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
#endif
if (argc > 1) {
close (0);
close (1);
close (2);
if (open (argv[1], O_RDWR) >= 0) {
dup (0);
dup (0);
} else {
#ifdef USE_SYSLOG
syslog (LOG_WARN, "cannot open %s\n", argv[1]);
closelog ();
#endif
exit (1);
}
}
if (access (PASSWD_FILE, 0) == -1) { /* must be a password file! */
printf ("No password file\n");
#ifdef USE_SYSLOG
syslog (LOG_WARN, "No password file\n");
closelog ();
#endif
exit (1);
}
#ifndef DEBUG
if (getppid () != 1) { /* parent must be INIT */
#ifdef USE_SYSLOG
syslog (LOG_WARN, "Pid == %d, not 1\n", getppid ());
closelog ();
#endif
exit (1);
}
#endif
if (! isatty (0) || ! isatty (1) || ! isatty (2)) {
#ifdef USE_SYSLOG
closelog ();
#endif
exit (1); /* must be a terminal */
}
while (*envp) /* add inherited environment, */
addenv (*envp++); /* some variables change later */
if ((cp = getdef_str("ENV_TZ")))
addenv (*cp == '/' ? tz(cp) : cp);
if ((cp = getdef_str("ENV_HZ")))
addenv (cp); /* set the default $HZ, if one */
(void) strcpy (name, "root"); /* KLUDGE!!! */
signal (SIGALRM, catch); /* exit if the timer expires */
alarm (ALARM); /* only wait so long ... */
while (1) { /* repeatedly get login/password pairs */
entry (name, &pwent); /* get entry from password file */
if (pwent.pw_name == (char *) 0) {
/*
* Fail secure
*/
printf ("No password entry for 'root'\n");
#ifdef USE_SYSLOG
syslog (LOG_WARN, "No password entry for 'root'\n");
closelog ();
#endif
exit (1);
}
/*
* Here we prompt for the root password, or if no password is
* given we just exit.
*/
/* get a password for root */
cp = getpass("Type control-d for normal startup,\n\
(or give root password for system maintenance):");
/* XXX - can't enter single user mode if root password is empty.
I think this is rare :-). But it will work with getpass()
from libc which doesn't return NULL on EOF. --marekm */
if (!cp || !*cp) {
#ifdef USE_SYSLOG
syslog (LOG_INFO, "Normal startup\n");
closelog ();
#endif
#ifdef TELINIT
execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) 0);
#endif
exit (0);
} else {
STRFCPY(pass, cp);
bzero (cp, strlen (cp));
}
if (pwent.pw_name && pwent.pw_passwd[0] == '@') {
if (pw_auth (pwent.pw_passwd + 1, name, PW_LOGIN, (char *) 0)) {
#ifdef USE_SYSLOG
syslog (LOG_WARN,
"Incorrect root authentication");
#endif
continue;
}
goto auth_done;
}
if (valid (pass, &pwent)) /* check encrypted passwords ... */
break; /* ... encrypted passwords matched */
puts ("Login incorrect");
#ifdef USE_SYSLOG
syslog (LOG_WARN, "Incorrect root password\n");
#endif
}
auth_done:
bzero (pass, strlen (pass));
alarm (0);
signal (SIGALRM, SIG_DFL);
environ = newenvp; /* make new environment active */
puts ("Entering System Maintenance Mode");
#ifdef USE_SYSLOG
syslog (LOG_INFO, "System Maintenance Mode\n");
#endif
/*
* Normally there would be a utmp entry for login to mung on
* to get the tty name, date, etc. from. We don't need all that
* stuff because we won't update the utmp or wtmp files. BUT!,
* we do need the tty name so we can set the permissions and
* ownership.
*/
if ((cp = ttyname (0))) { /* found entry in /dev/ */
if (strncmp(cp, "/dev/", 5) == 0)
cp += 5;
strncpy(utent.ut_line, cp, sizeof utent.ut_line);
}
if (getenv ("IFS")) /* don't export user IFS ... */
addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
setup (&pwent); /* set UID, GID, HOME, etc ... */
#ifdef USE_SYSLOG
closelog ();
#endif
shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
/*NOTREACHED*/
return (0);
}